import prettytable
from colorama import init, Fore, Back
from enum import Enum
import logging
import os
import copy
import subprocess

init(autoreset=False)

module_name='DDC_FARM'
isDocker = False
try:
    with open('/proc/1/cgroup') as f:
        if f.read().find('/docker/') == -1:
            prefix=''
except:
    prefix='./'    
configure_file= prefix +'/data/config.yaml'
ddan_key_file= prefix +'/data/DDAN_id_rsa'
logfilenmae = prefix +'/data/farms.log'

lgr = logging.getLogger(module_name)
# lgr.propagate = False


class ManuleCheckException(Exception):
    """
    Exception raised by failures, and need to stop do manual check.
    """
    def __init__(self,host,reason):
        self.host = host
        self.reason = reason

class Result(Enum):
    EXIT_CODE_OK = 0
    ERROR ='Error'
    EMPTY_VALUE = 'NoValue'
    OK = 'OK'
    FAIL = 'FAIL'
    ENABLE = 'TRUE'
    DISABLE = 'FALSE'

class CustomerTable():
    def __init__(self, title, rows, header=None, index_color=-1, **kwargs):
        self.tille = title
        self.rows = rows 
        self.header = header
        self.index_color = index_color
    
    @classmethod
    def add_table_rows(cls,tb,no_color=False,**kwargs):
        pt = prettytable.PrettyTable(field_names=tb.header,**kwargs)
        pt.align = 'l'
        index_color = tb.index_color
        for i in tb.rows:
            if index_color != -1:
                if i[index_color] in [Result.OK,Result.ENABLE]:
                    if no_color:
                        i[index_color] = i[index_color].value
                    else:
                        i[index_color] = Colored.green(i[index_color].value)
                elif i[index_color] in [Result.FAIL,Result.DISABLE]:
                    if no_color:
                        i[index_color] = i[index_color].value
                    else:
                        i[index_color] = Colored.red(i[index_color].value)
                else:
                    lgr.error('No support colored result {}'.format(i[index_color]))
            pt.add_row(i)
        return pt

def printTable(title,data=None,index_color=-1):
    data = [[]] if data is None else data
    tb = CustomerTable(title,data[1:],data[0],index_color=index_color)
    lgr.info(tb)

def checkNotEqual(orig,targ):
    if isinstance(orig,str):
        if orig.strip() != str(targ).strip():
            return True
    
    if isinstance(orig,list):
        orig.sort()
        targ.sort()
        if set(orig) != set(targ):
            return True
    return False

class filterStreamHandler(logging.StreamHandler):
    def __init__(self,stream = None):
        logging.StreamHandler.__init__(self,stream=stream)
    
    def emit(self, record):
        record = copy.deepcopy(record)
        if isinstance(record.msg,CustomerTable):
            title = record.msg.tille
            record.msg = CustomerTable.add_table_rows(record.msg)
            record.msg = "{}:\n{}".format(title,record.msg)
        super().emit(record)

class filterFileHandler(logging.FileHandler):
    def __init__(self,filename,**kwargs):
        super().__init__(filename,**kwargs)
    
    def emit(self, record):
        record = copy.deepcopy(record)
        if isinstance(record.msg,CustomerTable):
            title = record.msg.tille
            record.msg = CustomerTable.add_table_rows(record.msg,True)
            record.msg = "{}:\n{}".format(title,record.msg)
        super().emit(record)

def init_logger():
    # set formatter
    formatter_str = '%(asctime)s %(levelname)-8s[%(filename)s:%(lineno)d(%(funcName)s)] %(message)s'
    formatter = logging.Formatter(formatter_str)
    lgr.setLevel(logging.DEBUG)

    # File
    fh = filterFileHandler(logfilenmae)
    fh.setLevel(logging.DEBUG)
    fh.setFormatter(formatter)
    lgr.addHandler(fh)
   

    # Stream
    ch = filterStreamHandler()
    ch.setLevel(logging.DEBUG)
    ch.setFormatter(formatter)
    lgr.addHandler(ch)


class Colored():
    @classmethod
    def red(cls, s):
        return Fore.LIGHTRED_EX + str(s) + Fore.RESET
    @classmethod
    def green(cls, s):
        return Fore.LIGHTGREEN_EX + str(s) + Fore.RESET
    @classmethod
    def yellow(cls, s):
        return Fore.LIGHTYELLOW_EX + str(s) + Fore.RESET
    @classmethod
    def white(cls,s):
        return Fore.LIGHTWHITE_EX + str(s) + Fore.RESET
    @classmethod
    def blue(cls,s):
        return Fore.LIGHTBLUE_EX + str(s) + Fore.RESET

def exec_cmd(cmd):
    '''
    Execute a system command
    :param cmd:
    :return:
    '''
    if cmd is None:
        cmd=[]
        proc,stdout,stderr = (None,)*3

    lgr.info("cmd={}".format(cmd))
    try:
        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        (stdout, stderr) = proc.communicate()
    except:
        lgr.error('Fail to execute cmd {}'.format(cmd))
        return False, str(stdout).strip()

    lgr.debug( "cmd output=[%s]"%stdout.strip())
    if proc.returncode != 0:
        lgr.warning("execute command return code is [{}] error:{}".format(proc.returncode,stderr))

    return True, str(stdout).strip()

if __name__ == "__main__":
    init_logger()
    printTable('test table',[['a','b','c'],[11111,2,3],[4,5,Result.OK]],index_color=2)
    lgr.info('test')
    print(Result.EXIT_CODE_OK.value)